/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package core.reports;

import core.Amount;
import core.Barcode;
import core.CoreFacade;
import core.DataManager;
import core.Item;
import core.ItemManager;
import core.Product;
import core.ProductContainer;
import core.ProductGroup;
import core.ProductManager;
import core.StorageUnit;
import core.Unit;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;

/**
 *
 * @author Student
 */
public class ProductStatisticsGuideTest {
    private static CoreFacade model = null;
    private ItemManager itemManager = null;
    private ProductManager productManager = null;
    private ProductStatisticsGuide psg = null;
    
    public ProductStatisticsGuideTest() 
    {
        
    }
    
    @BeforeClass
    public static void setUpClass() 
    {
        System.out.println("Starting Product Statistics Guide Tests");
        System.out.println("SETUP: Start");
        //setup code
        CoreFacade.setDBMode(false);
        DataManager.setMode(false);
        DataManager.setTestMode(true);

        System.out.println("SETUP: DONE");
    }
    
    @AfterClass
    public static void tearDownClass() 
    {
        System.out.println("CLEANUP: Start");
		
        //clean up code
        CoreFacade.destroyInstance();

        System.out.println("CLEANUP: DONE");
        System.out.println("Finished Product Statistics Guide Test");
    }
    
    @Before
    public void setUp() 
    {
        System.out.println("-TEST: START");
        System.out.println("-TEST SETUP: START");

        System.out.println("-- Destroy Instance");
        CoreFacade.destroyInstance();
        model = null;

        System.out.println("-- Create new Instance");
        model = CoreFacade.getInstance();
        itemManager = ItemManager.getInstance();
        productManager = ProductManager.getInstance();
        psg = new ProductStatisticsGuide(6);

        System.out.println("-TEST SETUP: DONE");
    }
    
    @After
    public void tearDown() 
    {
        System.out.println("-TEST CLEANUP: START");
        //clean up everything we added
        System.out.println("-- Destroy Instance");
        model.destroyInstance2();
        CoreFacade.destroyInstance();
        model = null;
        itemManager.destroyInstance();
        itemManager = null;
        productManager.destroyInstance();
        productManager = null;
        psg = null;
        
        System.out.println("-TEST CLEANUP: DONE");
        System.out.println("-TEST: DONE");
    }
    
    /*
     * test 1
     */
    @Test
    public void Test1()
    {
        List<ProductStatisticsNode> psnl = psg.getProductStatistics();
        assertTrue(psnl.isEmpty());
    }
    
    /**
     * Test adding item of new product
     */
    @Test
    public void Test2()
    {
        StorageUnit su = addSU(1);
        Product p = createProduct1();
        Item i = createItem1(p, su);
        
        productManager.addProduct(p);
        itemManager.addItem(i);
        
        List<ProductStatisticsNode> psnl = psg.getProductStatistics();
        assertTrue(psnl.size() == 1);
        
        ProductStatisticsNode psgn = psnl.get(0);
        
        assertTrue(Double.parseDouble(psgn.getSupplyCur()) <= 1);
        assertTrue(Double.parseDouble(psgn.getSupplyAve()) <= .4);
        assertTrue(Double.parseDouble(psgn.getSupplyMin()) <= 0);
        assertTrue(Double.parseDouble(psgn.getSupplyMax()) <= 1);
        assertTrue(Double.parseDouble(psgn.getSupplyUsed()) <= 0);
        assertTrue(Double.parseDouble(psgn.getSupplyAdded()) <= 1);
        String usedAveAge = psgn.getUsedAvg();
        String[] sa = usedAveAge.split("\\s");
        usedAveAge = sa[1];
        assertTrue(Double.parseDouble(usedAveAge) == 0);
        String usedAveMax = psgn.getUsedMax();
        sa = usedAveMax.split("\\s");
        usedAveMax = sa[1];
        assertTrue(Double.parseDouble(usedAveMax) == 0);
        assertTrue(Double.parseDouble(psgn.getCurAvg()) >= 64);
        assertTrue(Double.parseDouble(psgn.getCurMax()) >= 64);
    }
    
    /**
     * Test adding a new item of an old product
     */
    @Test
    public void Test3()
    {
        StorageUnit su = addSU(2);
        Product p = createProduct1();
        Item i = createItem1(p, su);
        
        productManager.addProduct(p);
        itemManager.addItem(i);
        Item i2 = createItem2(p, su);
        itemManager.addItem(i2);
        
        List<ProductStatisticsNode> psnl = psg.getProductStatistics();
        assertTrue(psnl.size() == 1);
        
        ProductStatisticsNode psgn = psnl.get(0);
        
        assertTrue(Double.parseDouble(psgn.getSupplyCur()) <= 2);
        assertTrue(Double.parseDouble(psgn.getSupplyAve()) <= .7);
        assertTrue(Double.parseDouble(psgn.getSupplyMin()) <= 0);
        assertTrue(Double.parseDouble(psgn.getSupplyMax()) <= 2);
        assertTrue(Double.parseDouble(psgn.getSupplyUsed()) <= 0);
        assertTrue(Double.parseDouble(psgn.getSupplyAdded()) <= 2);
        String usedAveAge = psgn.getUsedAvg();
        String[] sa = usedAveAge.split("\\s");
        usedAveAge = sa[1];
        assertTrue(Double.parseDouble(usedAveAge) == 0);
        String usedAveMax = psgn.getUsedMax();
        sa = usedAveMax.split("\\s");
        usedAveMax = sa[1];
        assertTrue(Double.parseDouble(usedAveMax) == 0);
        assertTrue(Double.parseDouble(psgn.getCurAvg()) >= 63.5);
        assertTrue(Double.parseDouble(psgn.getCurMax()) >= 64);
    }
    
    /**
     * Test adding a new item of an old product
     */
    @Test
    public void Test4()
    {
        StorageUnit su = addSU(3);
        Product p = createProduct1();
        Item i = createItem1(p, su);
        
        productManager.addProduct(p);
        itemManager.addItem(i);
        Item i2 = createItem2(p, su);
        itemManager.addItem(i2);
        
        Product p2 = createProduct2();
        Item i3 = createItem3(p2, su);
        
        productManager.addProduct(p2);
        itemManager.addItem(i3);
        
        List<ProductStatisticsNode> psnl = psg.getProductStatistics();
        assertTrue(psnl.size() == 2);
        
        //get first product
        ProductStatisticsNode psgn = psnl.get(0);
        //check that second product didn't effect the first
        assertTrue(Double.parseDouble(psgn.getSupplyCur()) <= 2);
        assertTrue(Double.parseDouble(psgn.getSupplyAve()) <= .7);
        assertTrue(Double.parseDouble(psgn.getSupplyMin()) <= 0);
        assertTrue(Double.parseDouble(psgn.getSupplyMax()) <= 2);
        assertTrue(Double.parseDouble(psgn.getSupplyUsed()) <= 0);
        assertTrue(Double.parseDouble(psgn.getSupplyAdded()) <= 2);
        String usedAveAge = psgn.getUsedAvg();
        String[] sa = usedAveAge.split("\\s");
        usedAveAge = sa[1];
        assertTrue(Double.parseDouble(usedAveAge) == 0);
        String usedAveMax = psgn.getUsedMax();
        sa = usedAveMax.split("\\s");
        usedAveMax = sa[1];
        assertTrue(Double.parseDouble(usedAveMax) == 0);
        assertTrue(Double.parseDouble(psgn.getCurAvg()) >= 63.5);
        assertTrue(Double.parseDouble(psgn.getCurMax()) >= 64);
        
        //get second product
        psgn = psnl.get(1);
        //check that second product didn't effect the first
        assertTrue(Double.parseDouble(psgn.getSupplyCur()) <= 1);
        assertTrue(Double.parseDouble(psgn.getSupplyAve()) <= .5);
        assertTrue(Double.parseDouble(psgn.getSupplyMin()) <= 1);
        assertTrue(Double.parseDouble(psgn.getSupplyMax()) <= 1);
        assertTrue(Double.parseDouble(psgn.getSupplyUsed()) <= 0);
        assertTrue(Double.parseDouble(psgn.getSupplyAdded()) <= 1);
        usedAveAge = psgn.getUsedAvg();
        sa = usedAveAge.split("\\s");
        usedAveAge = sa[1];
        assertTrue(Double.parseDouble(usedAveAge) == 0);
        usedAveMax = psgn.getUsedMax();
        sa = usedAveMax.split("\\s");
        usedAveMax = sa[1];
        assertTrue(Double.parseDouble(usedAveMax) == 0);
        assertTrue(Double.parseDouble(psgn.getCurAvg()) >= 94.0);
        assertTrue(Double.parseDouble(psgn.getCurMax()) >= 94.0);
    }
    /**
     * Test adding a new item of an old product
     */
    @Test
    public void Test5()
    {
        StorageUnit su = addSU(4);
        Product p = createProduct1();
        Item i = createItem1(p, su);
        
        productManager.addProduct(p);
        itemManager.addItem(i);
        
        List<ProductStatisticsNode> psnl = psg.getProductStatistics();
        ProductStatisticsNode psgn = psnl.get(0);
        
        assertTrue(psgn.getDescription().equals("beans"));
        assertTrue(psgn.getSize().equals("3.0 count"));
        assertTrue(psgn.getThreeMonthSupply().equals("1"));
        assertTrue(psgn.getShelfLife().equals("3"));
        
        Product p2 = createProduct3();
        
        productManager.Initialize();
        productManager.editProduct(p, p2);
        
        psnl = psg.getProductStatistics();
        psgn = psnl.get(1);
        
        assertTrue(psgn.getDescription().equals("coffee"));
        assertTrue(psgn.getSize().equals("1.0 count"));
        assertTrue(psgn.getThreeMonthSupply().equals("1"));
        assertTrue(psgn.getShelfLife().equals("3"));
    }
    
    
    private StorageUnit addSU(int suNumber)
    {
        StorageUnit su = null;
        try {
            su = model.addStorageUnit("su" + suNumber);
        } catch (Exception ex) 
        {
            fail("adding storage unit threw an exception.");
        }
        
        return su;
    }
    
    private Product createProduct1()
    {
        Calendar creationDate = new GregorianCalendar();
        creationDate.roll(Calendar.MONTH, -4);
        Amount a = new Amount(Unit.createUnit("count"), 3);
        Product p = new Product(creationDate, new Barcode("123"), "beans", a, 3, 1);
        return p;
    }
    
    private Product createProduct2() 
    {
        Calendar creationDate = new GregorianCalendar();
        creationDate.roll(Calendar.MONTH, -2);
        Amount a = new Amount(Unit.createUnit("count"), 2);
        Product p = new Product(creationDate, new Barcode("234"), "pork", a, 3, 1);
        return p;
    }
    
    private Product createProduct3()
    {
        Calendar creationDate = new GregorianCalendar();
        creationDate.roll(Calendar.MONTH, -1);
        Amount a = new Amount(Unit.createUnit("count"), 1);
        Product p = new Product(creationDate, new Barcode("123"), "coffee", a, 3, 1);
        return p;
    }
    
    private Item createItem1(Product p, ProductContainer pc)
    {
        Calendar entryDate = new GregorianCalendar();
        entryDate.roll(Calendar.DAY_OF_MONTH, -2);
        entryDate.roll(Calendar.MONTH, -3);
        
        Item i = new Item(p, pc, entryDate, ItemManager.getInstance().generateBarcode());
        return i;
    }
    
    private Item createItem2(Product p, ProductContainer pc)
    {
        Calendar entryDate = new GregorianCalendar();
        entryDate.roll(Calendar.DAY_OF_MONTH, -1);
        entryDate.roll(Calendar.MONTH, -2);
        
        Item i = new Item(p, pc, entryDate, ItemManager.getInstance().generateBarcode());
        return i;
    }

    private Item createItem3(Product p, StorageUnit pc) 
    {
        Calendar entryDate = new GregorianCalendar();
        entryDate.roll(Calendar.DAY_OF_MONTH, -2);
        entryDate.roll(Calendar.MONTH, -4);
        
        Item i = new Item(p, pc, entryDate, ItemManager.getInstance().generateBarcode());
        return i;
        
    }
}
